package Service;

import Service.DataCenter;
import Service.ADJUSTMENTFACTOR;
import facecat.topin.service.*;
import facecat.topin.core.*;
import java.util.*;

/*
 * 历史数据服务
 */
public class HistoryServiceClient extends FCClientService {
    public HistoryServiceClient()
    {
        setServiceID(SERVICEID);
    }

    public static int SERVICEID = 10001;

    //获取数据
    public static int FUNCTIONID_GETDATA = 0;

    //获取代码
    public int FUNCTIONID_GETCODE = 1;

    //获取复权因子
    public int FUNCTIONID_GETDR = 2;

    //获取数据2
    public static int FUNCTIONID_GETDATA2 = 3;

    private int m_socketID;

    /*
     * 获取套接字
     */
    public int getSocketID()
    {
        return m_socketID;
    }

    /*
     * 设置套接字
     *@param value
     */
    public void setSocketID(int value)
    {
        m_socketID = value;
    }

    /*
     * 请求代码
     *@param requestID 请求ID
     */
    public void reqCodes(int requestID)
    {
        FCBinary bw = new FCBinary();
        try{
        bw.writeString("1");
        byte[] bytes = bw.getBytes();
        bw.close();
        int ret = send(new FCMessage(getServiceID(), FUNCTIONID_GETCODE, requestID, m_socketID, 0, getCompressType(), bytes.length, bytes));
        }catch(Exception ex){
            
        }
    }

    /*
     * 请求数据
     *@param request_ID 请求ID
     *@param code 代码
     *@param cycle 周期
     *@param startDate 开始日期
     *@param endDate 结束日期
     */
    public void reqData(int requestID, String code, int cycle, int subscription, double startDate, double endDate)
    {
        FCBinary bw = new FCBinary();
        try{
        bw.writeString(code);
        bw.writeInt(cycle);
        bw.writeDouble(startDate);
        bw.writeDouble(endDate);
        bw.writeInt(subscription);
        byte[] bytes = bw.getBytes();
        bw.close();
        int ret = send(new FCMessage(getServiceID(), FUNCTIONID_GETDATA, requestID, m_socketID, 0, getCompressType(), bytes.length, bytes));
        }catch(Exception ex){
            
        }
    }

    /*
     * 请求数据
     *@param request_ID
     *@param code
     *@param oldRequestID
     */
    public void reqData2(int requestID, String code, int oldRequestID)
    {
        FCBinary bw = new FCBinary();
        try{
        bw.writeString(code);
        bw.writeInt(oldRequestID);
        byte[] bytes = bw.getBytes();
        bw.close();
        int ret = send(new FCMessage(getServiceID(), FUNCTIONID_GETDATA2, requestID, m_socketID, 0, getCompressType(), bytes.length, bytes));
        }catch(Exception ex){
            
        }
    }

    /*
     * 请求复权因子
     */
    public void reqDevideDatas(int requestID)
    {
        FCBinary bw = new FCBinary();
        try{
            bw.writeInt(0);
            byte[] bytes = bw.getBytes();
            bw.close();
            int ret = send(new FCMessage(getServiceID(), FUNCTIONID_GETDR, requestID, m_socketID, 0, 0, bytes.length, bytes));
        }catch(Exception ex){
         
        }
    }

    /*
     * 获取数据
     *@param code 代码
     *@param cycle 周期
     *@param startDate 开始日期
     *@param endDate 结束日期
     *@param nowDate 当前日期
     *@param nowVolume 当前成交量
     *@param nowAmount 当前成交额
     *@param body 包体
     *@param bodyLength 包体长度
     */
    public static ArrayList<SecurityData> getDatas(RefObject<String> refCode, RefObject<Integer> refCycle, RefObject<Double> refStartDate, RefObject<Double> refEndDate, RefObject<Integer> refSubscription, RefObject<Double> refNowDate, RefObject<Double> refNowVolume, RefObject<Double> refNowAmount, byte[] body, int bodyLength)
    {
       
        FCBinary br = new FCBinary();
        try{
            br.write(body, bodyLength);
            refCode.argvalue = br.readString();
            refCycle.argvalue = br.readInt();
            refStartDate.argvalue = br.readDouble();
            refEndDate.argvalue = br.readDouble();
            refSubscription.argvalue = br.readInt();
            refNowDate.argvalue = br.readDouble();
            refNowVolume.argvalue = br.readDouble();
            refNowAmount.argvalue = br.readDouble();
            String code = refCode.argvalue;
            int cycle = refCycle.argvalue; 
            double startDate = refStartDate.argvalue;
            double endDate = refEndDate.argvalue;
            int subscription = refSubscription.argvalue;
            double nowDate = refNowDate.argvalue;
            double nowVolume = refNowVolume.argvalue;
            double nowAmount = refNowAmount.argvalue;
            int datasSize = br.readInt();
            ArrayList<SecurityData> datas = new ArrayList<SecurityData>();
            boolean seDate = (cycle != 0 && cycle != 1 && cycle != 1440);
            for (int i = 0; i < datasSize; i++)
            {
                SecurityData data = new SecurityData();
                if (cycle >= 1440)
                {
                    data.m_date = br.readShort() * 86400;
                }
                else
                {
                    data.m_date = br.readInt() * 60;
                }
                data.m_close = br.readDouble();
                data.m_high = br.readDouble();
                data.m_low = br.readDouble();
                data.m_open = br.readDouble();
                int type = br.readByte();
                if (type == 0)
                {
                    data.m_volume = br.readDouble();
                    data.m_amount = br.readDouble();
                }
                else
                {
                    data.m_volume = br.readInt();
                    data.m_amount = br.readInt();
                }
                if (seDate)
                {
                    if (cycle >= 1440)
                    {
                        data.m_startDate = br.readShort() * 86400;
                        data.m_endDate = br.readShort() * 86400;
                    }
                    else
                    {
                        data.m_startDate = br.readInt() * 60;
                        data.m_endDate = br.readInt() * 60;
                    }
                }
                if (cycle > 0 && data.m_volume == 0)
                {
                    continue;
                }
                datas.add(data);
            }
            br.close();
            return datas;
        }catch(Exception ex){
            return null;
        }
    }

    public static void getDatas2(RefObject<String> code, ArrayList<SecurityData> dayDatas, ArrayList<SecurityData> minuteDatas, ArrayList<SecurityData> trendDatas, byte[] body, int bodyLength)
    {
        FCBinary br = new FCBinary();
        try{
            br.write(body, bodyLength);
            code.argvalue = br.readString();

            ArrayList<SecurityData> datas = null;
            for (int d = 0; d < 3; d++)
            {
                if (d == 0)
                {
                    datas = dayDatas;
                }
                else if (d == 1)
                {
                    datas = minuteDatas;
                }
                else
                {
                    datas = trendDatas;
                }
                int datasSize = br.readInt();
                for (int i = 0; i < datasSize; i++)
                {
                    SecurityData data = new SecurityData();
                    if (d == 0)
                    {
                        data.m_date = br.readShort() * 86400;
                    }
                    else
                    {
                        data.m_date = br.readInt() * 60;
                    }
                    int type2 = br.readByte();
                    if (type2 == 1)
                    {
                        data.m_close = (double)br.readShort() / 100;
                        data.m_high = (double)br.readShort() / 100;
                        data.m_low = (double)br.readShort() / 100;
                        data.m_open = (double)br.readShort() / 100;
                    }
                    else
                    {
                        data.m_close = br.readDouble();
                        data.m_high = br.readDouble();
                        data.m_low = br.readDouble();
                        data.m_open = br.readDouble();
                    }
                    int type = br.readByte();
                    if (type == 0)
                    {
                        data.m_volume = br.readDouble();
                        data.m_amount = br.readDouble();
                    }
                    else
                    {
                        data.m_volume = br.readInt();
                        data.m_amount = br.readInt();
                    }
                    if (d < 2 && data.m_volume == 0)
                    {
                        continue;
                    }
                    datas.add(data);
                }
            }
            br.close();
        }catch(Exception ex){
            
        }
    }

    /*
     * 获取代码
     *param body 包体
     *param bodyLength 包头长度
     */
    public static ArrayList<Security> getCodes(byte[] body, int bodyLength)
    {
        FCBinary br = new FCBinary();
        try{
            br.write(body, bodyLength);
            int datasSize = br.readInt();
            ArrayList<Security> datas = new ArrayList<Security>();
            for (int i = 0; i < datasSize; i++)
            {
                Security security = new Security();
                security.m_code = br.readString();
                security.m_name = br.readString();
                security.m_pingyin = br.readString();
                security.m_type = br.readByte();
                security.m_block = br.readString();
                datas.add(security);
            }
            br.close();
            return datas;
        }catch(Exception ex){
            return null;
        }
    }

    /*
     * 解析复权因子
     *@param body
     *@param bodyLength
     */
    public HashMap<String, ArrayList<ADJUSTMENTFACTOR>> getFactors(byte[] body, int bodyLength)
    {
        HashMap<String, ArrayList<ADJUSTMENTFACTOR>> factors = new HashMap<String, ArrayList<ADJUSTMENTFACTOR>>();
        FCBinary br = new FCBinary();
        try{
            br.write(body, bodyLength);
            int size = br.readInt();
            for (int i = 0; i < size; i++)
            {
                String code = br.readString();
                int dfSize = br.readInt();
                ArrayList<ADJUSTMENTFACTOR> aList = new ArrayList<ADJUSTMENTFACTOR>();
                for (int j = 0; j < dfSize; j++)
                {
                    ADJUSTMENTFACTOR af = new ADJUSTMENTFACTOR();
                    af.dwDate = (double)br.readInt() * 86400;
                    af.f1 = br.readFloat();
                    af.f2 = br.readFloat();
                    af.f3 = br.readFloat();
                    af.f4 = br.readFloat();
                    aList.add(af);
                }
                factors.put(code, aList);
            }
            br.close();
        return factors;
        }catch(Exception ex){
            return null;
        }
    }

    /*
     * 接受消息方法
     */
    public void onReceive(FCMessage message)
    {
        super.onReceive(message);
        if (message.m_functionID == FUNCTIONID_GETCODE)
        {
            ArrayList<Security> securities = getCodes(message.m_body, message.m_bodyLength);
            DataCenter.m_securityService.load(securities);
        }
        else if (message.m_functionID == FUNCTIONID_GETDR)
        {
            StockService.m_factors = getFactors(message.m_body, message.m_bodyLength);
        }
        sendToListener(message);
    }   
}
